package com.zjcode.cdcer.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.chinatechstar.component.commons.exception.ServiceException;
import com.zjcode.cdcer.model.excel.SelfTestTableVo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.ss.formula.functions.T;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author yanghaolin
 * @date 2022/7/25
 * @apiNote EasyExcel工具类处理
 */
public class ExcelUtil {

    /**
     * 导出Excel
     *
     * @param headList  Excel表头列表
     * @param dataList  Excel内容列表
     * @param sheetName Excel工作表名称
     * @param response  响应对象
     * @throws IOException
     */
    public static void exportExcel(List<String> headList, List<LinkedHashMap<String, Object>> dataList, String sheetName, HttpServletResponse response)
            throws IOException {
        ServletOutputStream servletOutputStream = null;
        try {
            servletOutputStream = response.getOutputStream();
            response.setContentType("multipart/form-data");
            response.setCharacterEncoding("utf-8");
            String fileName = new String((sheetName + new SimpleDateFormat("yyyy-MM-dd").format(new Date())).getBytes(), StandardCharsets.UTF_8);
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
            ExcelWriter writer = new ExcelWriter(servletOutputStream, ExcelTypeEnum.XLSX, true);
            Sheet sheet = new Sheet(1, 0);
            sheet.setSheetName(sheetName);

            Table table = new Table(1);
            List<List<String>> head = new ArrayList<>();
            if (!CollectionUtils.isEmpty(headList)) {
                headList.forEach(headName -> head.add(Arrays.asList(headName)));
            }
            table.setHead(head);

            List<List<String>> data = new ArrayList<>();
            if (!CollectionUtils.isEmpty(dataList)) {
                dataList.forEach(map -> {
                    List<String> list = new ArrayList<>();
                    for (Map.Entry<String, Object> entry : map.entrySet()) {
                        Object value = entry.getValue();
                        list.add(value == null ? null : value.toString());
                    }
                    data.add(list);
                });
            }

            writer.write0(data, sheet, table);
            writer.finish();
            servletOutputStream.flush();
        } catch (IOException e) {
            throw new ServiceException(e.toString());
        } finally {
            if (servletOutputStream != null) {
                servletOutputStream.close();
            }
        }
    }


    public static <T> void exportExcelObject(List<String> headList, List<T> dataList, String sheetName, HttpServletResponse response)
            throws IOException {
        ServletOutputStream servletOutputStream = null;
        try {
            servletOutputStream = response.getOutputStream();
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = new String((sheetName + new SimpleDateFormat("yyyy-MM-dd").format(new Date())).getBytes(), StandardCharsets.ISO_8859_1);
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");

            List<List<String>> data = new ArrayList<>();
            if (!CollectionUtils.isEmpty(dataList)) {
                Field[] fields = dataList.get(0).getClass().getDeclaredFields();
                for (T entity : dataList) {
                    List<String> row = new ArrayList<>();
                    for (Field field : fields) {
                        field.setAccessible(true);
                        Object value = field.get(entity);
                        row.add(value == null ? null : value.toString());
                    }
                    data.add(row);
                }
            }
            List<List<String>> head = new ArrayList<>();
            head.add(headList);

            EasyExcel.write(servletOutputStream)
                    .head(head)
                    .sheet(sheetName)
                    .doWrite(data);

            servletOutputStream.flush();
        } catch (IOException | IllegalAccessException e) {
            throw new ServiceException(e.toString());
        } finally {
            if (servletOutputStream != null) {
                servletOutputStream.close();
            }
        }
    }


    /**
     * 设置响应结果
     *
     * @param response    响应结果对象
     * @param rawFileName 文件名
     * @throws UnsupportedEncodingException 不支持编码异常
     */
    public static void setExcelResponseProp(HttpServletResponse response, String rawFileName) throws UnsupportedEncodingException {
        response.setContentType("multipart/form-data");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode(rawFileName, "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    }

    public static void writeExportEasyExcel(HttpServletResponse response, List<SelfTestTableVo> list, String sheetName,String fileName){
        try{
            // 设置文本内省
            response.setContentType("application/vnd.ms-excel");
            // 设置字符编码
            response.setCharacterEncoding("utf-8");
            // 设置响应头
            response.setHeader("Content-disposition", "attachment;filename="+fileName+".xlsx");
            EasyExcel.write(response.getOutputStream(), SelfTestTableVo.class).sheet(sheetName).doWrite(list);
        }catch (NullPointerException e){
            e.getMessage();
        }catch (Exception e){
            e.getMessage();
        }
    }
}
